/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cn.tang.tframe.common.utils;

import cn.tang.tframe.common.utils.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 金鑫
 * 
 * @author jinxin
 *
 */
public class DateUtils {
	private static Logger logger = LoggerFactory.getLogger(DateUtils.class);

	private static final GregorianCalendar calendar = (GregorianCalendar) GregorianCalendar.getInstance();

	public static final Date FIRST_DATE = new Date(0);


	/**
	 * list all dates between start date and end date, both day included
	 *
	 * @param start
	 * @param end
	 * @return
	 */
	public static List<Date> listDates(Date start, Date end) {
		List<Date> dates = new ArrayList<>();

		Date date = start;
		calendar.setTime(start);
		while (date.before(end)) {
			dates.add(date);
			calendar.add(Calendar.DAY_OF_WEEK, 1);
			date = calendar.getTime();
		}
		if (date.equals(end)) {
			dates.add(end);
		}

		return dates;
	}

	/**
	 * return the 0'clock time for a date, like 2013/8/1 0:0:0
	 *
	 * @param date
	 * @return
	 */
	public static Date get0OClock(Date date) {
		if (date == null) {
			return null;
		}

		calendar.setTime(date);
		int year = calendar.get(Calendar.YEAR);
		int month = calendar.get(Calendar.MONTH);
		int day = calendar.get(Calendar.DAY_OF_MONTH);
		calendar.set(year, month, day, 0, 0, 0);
		return calendar.getTime();
	}


	public static Date parse(final String str, final String pattern) {
		if (StringUtils.isBlank(str)) {
			return null;
		}
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		try {
			return sdf.parse(str);
		} catch (Exception e) {
			return null;
		}
	}

	public static String format(final Date date, final String pattern) {
		if (date == null) {
			return null;
		}
		try {
			SimpleDateFormat sdf = new SimpleDateFormat(pattern);
			return sdf.format(date);
		} catch (Exception e) {
			return null;
		}
	}

	public static int daysBetween(Date startDate, Date endDate) {
		if (startDate == null || endDate == null) {
			logger.warn("空日期无法计算间隔日期,start:{} , endDate:{}", startDate, endDate);
			return 0;
		}
		Calendar fromCalendar = Calendar.getInstance();
		fromCalendar.setTime(startDate);
		fromCalendar.set(Calendar.HOUR_OF_DAY, 0);
		fromCalendar.set(Calendar.MINUTE, 0);
		fromCalendar.set(Calendar.SECOND, 0);
		fromCalendar.set(Calendar.MILLISECOND, 0);

		Calendar toCalendar = Calendar.getInstance();
		toCalendar.setTime(endDate);
		toCalendar.set(Calendar.HOUR_OF_DAY, 0);
		toCalendar.set(Calendar.MINUTE, 0);
		toCalendar.set(Calendar.SECOND, 0);
		toCalendar.set(Calendar.MILLISECOND, 0);

		return (int) ((toCalendar.getTime().getTime() - fromCalendar.getTime().getTime()) / (1000 * 60 * 60 * 24));
	}
	public static int yearsBetween(Date startDate, Date endDate) {
		if (startDate == null || endDate == null) {
			logger.debug("空日期无法计算间隔日期,start:{} , endDate:{}", startDate, endDate);
			return 0;
		}
		int startYear = getYear(startDate);
		int endYear = getYear(endDate);
		int i = endYear - startYear;
		return Math.max(i,1);
	}


	/**
	 * 获取指定日期的年份
	 *
	 * @param date
	 * @return
	 */
	public static int getYear(Date date) {

		if(null == date)
			return -1;
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);

		return calendar.get(Calendar.YEAR);
	}

	/**
	 * 获取指定日期的年份
	 *
	 * @return
	 */
	public static int getYear(long millis) {

		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(millis);

		return calendar.get(Calendar.YEAR);
	}

	/**
	 * 获取指定日期的月份
	 *
	 * @param date
	 * @return
	 */
	public static int getMonth(Date date) {

		if(null == date)
			return -1;
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);

		return (calendar.get(Calendar.MONTH) + 1);
	}

	/**
	 * 获取指定日期的月份
	 *
	 * @return
	 */
	public static int getMonth(long millis) {

		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(millis);

		return (calendar.get(Calendar.MONTH) + 1);
	}

	/**
	 * 获取指定的日期的日(月份中的天数)
	 *
	 * @param date
	 * @return
	 */
	public static int getDay(Date date) {

		if(null == date)
			return -1;
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);

		return calendar.get(Calendar.DAY_OF_MONTH);
	}

	/**
	 * 获取指定的日期的日(月份中的天数)
	 *
	 * @return
	 */
	public static int getDay(long millis) {

		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(millis);

		return calendar.get(Calendar.DAY_OF_MONTH);
	}

	/**
	 * 获取指定的日期的日(年份中的天数)
	 *
	 * @param date
	 * @return
	 */
	public static int getDayOfYear(Date date) {

		if(null == date)
			return -1;
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);

		return calendar.get(Calendar.DAY_OF_YEAR);
	}

	/**
	 * 获取指定的日期的日(年中的天数)
	 *
	 * @return
	 */
	public static int getDayOfYear(long millis) {

		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(millis);

		return calendar.get(Calendar.DAY_OF_YEAR);
	}
	/**
	 * 某日期前几天
	 * 
	 * @param date
	 * @param day
	 *            负数
	 * @return
	 */
	public static Date before(Date date, Integer day) {
		Calendar beforeNow = Calendar.getInstance();
		beforeNow.setTime(date);
		beforeNow.add(Calendar.DATE, day);// 你要加减的日期
		return beforeNow.getTime();

	}


	/**
	 * 返回某天的开始时间
	 * 
	 * @param date
	 * @return
	 */
	public static Date begin(Date date) {
		if (null == date) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MINUTE, 0);
		return c.getTime();
	}

	/**
	 * 返回某天的结束时间
	 * 
	 * @param date
	 * @return
	 */
	public static Date end(Date date) {
		if (null == date) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.HOUR_OF_DAY, 23);
		c.set(Calendar.SECOND, 59);
		c.set(Calendar.MINUTE, 59);
		return c.getTime();
	}

	/**
	 * 返回某天的开始时间
	 * 
	 * @param date
	 * @return
	 */
	public static String begin(String date) {
		if (StringUtils.isBlank(date)) {
			return null;
		}
		try {
			return format(begin(parse(date, "yyyy-MM-dd")), "yyyy-MM-dd HH:mm:ss");
		} catch (Exception e) {
		}
		return null;
	}

	/**
	 * 返回某天的结束时间
	 * 
	 * @param date
	 * @return
	 */
	public static String end(String date) {
		if (StringUtils.isBlank(date)) {
			return null;
		}
		try {
			return format(end(parse(date, "yyyy-MM-dd")), "yyyy-MM-dd HH:mm:ss");
		} catch (Exception e) {
		}
		return null;
	}

	/**
	 * 两个时间中相差多少秒
	 * 
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	public static int secondsBetween(Date startDate, Date endDate) {
		if (startDate == null || endDate == null) {
			logger.warn("空日期无法计算间隔日期,start:{} , endDate:{}", startDate, endDate);
			return 0;
		}
		Calendar fromCalendar = Calendar.getInstance();
		fromCalendar.setTime(startDate);
		Calendar toCalendar = Calendar.getInstance();
		toCalendar.setTime(endDate);
		return (int) ((toCalendar.getTime().getTime() - fromCalendar.getTime().getTime()) / (1000));
	}

	/**
	 * 返回某月的开始时间
	 * 
	 * @param date
	 * @return
	 */
	public static Date getFirstDateOfMonth(Date date) {
		if (null == date) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.DAY_OF_MONTH, c.getActualMinimum(Calendar.DAY_OF_MONTH));
		return c.getTime();
	}

	/**
	 * 返回某月的结束时间
	 * 
	 * @param date
	 * @return
	 */
	public static Date getLastDateOfMonth(Date date) {
		if (null == date) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
		c.set(Calendar.HOUR_OF_DAY, 23);
		c.set(Calendar.SECOND, 59);
		c.set(Calendar.MINUTE, 59);
		return c.getTime();
	}

	/**
	 * 返回某年的开始时间
	 * 
	 * @param date
	 * @return
	 */
	public static Date getFirstDateOfYear(Date date) {
		if (null == date) {
			return null;
		}
		calendar.setTime(date);
		int year = calendar.get(Calendar.YEAR);
		calendar.set(year, 0, 1, 0, 0, 0);
		return calendar.getTime();
	}

	/**
	 * 返回某月的结束时间
	 * 
	 * @param date
	 * @return
	 */
	public static Date getLastDateOfYear(Date date) {
		if (null == date) {
			return null;
		}
		calendar.setTime(date);
		int year = calendar.get(Calendar.YEAR);
		calendar.set(year, 12, 31, 23, 59, 59);
		return calendar.getTime();
	}

	/**
	 * 日期只保留年月日，清除时分秒
	 */
	public static String clearTimeOfDate(String date) {
		int dateLength = 10;
		if (null == date) {
			return null;
		}
		date = date.trim();
		if (StringUtils.isNotBlank(date) && date.length() > dateLength) {
			return date.substring(0, dateLength);
		}
		return date;
	}

	/**
	 * 日期格式字符串转换成时间戳
	 *
	 * @param dateStr 字符串日期
	 * @param format   如：yyyy-MM-dd HH:mm:ss
	 *
	 * @return
	 */
	public static Long Date2TimeStamp(String dateStr, String format) {
		try {
			SimpleDateFormat sdf = new SimpleDateFormat(format);
			return sdf.parse(dateStr).getTime() / 1000;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return 0l;
	}

	/**
	 * Java将Unix时间戳转换成指定格式日期字符串
	 * @param timestampString 时间戳 如："1473048265";
	 * @param formats 要格式化的格式 默认："yyyy-MM-dd HH:mm:ss";
	 *
	 * @return 返回结果 如："2016-09-05 16:06:42";
	 */
	public static String TimeStamp2Date(String timestampString, String formats) {
		if(formats=="") {
			formats = "yyyy-MM-dd HH:mm:ss";
		}
		Long timestamp = Long.parseLong(timestampString) * 1000;
		String date = new SimpleDateFormat(formats, Locale.CHINA).format(new Date(timestamp));
		return date;
	}

	public static void main(String[] args) {
		long start = DateUtils.parse("2017-02-01 10:00:00", "yyyy-MM-dd HH:mm:ss").getTime();
		long end = DateUtils.parse("2017-02-01 10:20:00", "yyyy-MM-dd HH:mm:ss").getTime();
		System.out.println(start);
		System.out.println(end);
		System.out.println(new Date(1487562495823L));
		Date d = new Date();
		System.out.println(daysBetween(parse("20160702010101","yyyyMMddHHmmss"),parse("20160702020101","yyyyMMddHHmmss")));
		System.out.println(daysBetween(parse("20160702010101","yyyyMMddHHmmss"),parse("20160702020101","yyyyMMddHHmmss")));
	}
}
